import "@site/src/languages/highlight";
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

# 创建物理节点 I

&emsp;&emsp;在本教程中，我们将学习如何在 Dora SSR 游戏引擎中创建物理刚体节点对象，并设置不同物理对象之间的分组和碰撞关系。通过以下步骤，您将能够在物理世界中实现基础的物体重力运动、形状设置和碰撞检测。

## 1. 创建物理世界与重力

&emsp;&emsp;首先，我们需要定义一个物理世界，并设置其重力方向和大小。在此示例中，重力被定义为垂直向下，大小为 `-10`。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local Vec2 <const> = require("Vec2")
local PhysicsWorld <const> = require("PhysicsWorld")

local gravity <const> = Vec2(0, -10) -- 定义重力方向和大小
local world = PhysicsWorld() -- 创建物理世界
world.y = -200 -- 调整物理世界的y轴位置
```

</TabItem>
</Tabs>

## 2. 定义物理刚体

&emsp;&emsp;物理刚体可以是静态（Static）或动态（Dynamic）的。静态刚体用于不可移动的物体（如地面），动态刚体则用于可移动的物体（如角色或障碍物）。此外物理刚体还有运动态（Kinematic）类型，用于定义具有无限大的质量但可以控制其进行运动的物体。

### 定义静态地形刚体

&emsp;&emsp;静态刚体常用于地面或墙体，通常不会受到重力影响。在下例中，我们创建了一个静态的地形刚体，并设置其为800x10的多边形形状。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local BodyDef <const> = require("BodyDef")

local terrainDef = BodyDef()
terrainDef.type = "Static" -- 设置为静态刚体
terrainDef:attachPolygon(800, 10, 1, 0.8, 0.2) -- 附加一个宽800高10的矩形多边形
-- 注意 1, 0.8, 0.2 的参数分别为密度、摩擦系数和弹性系数
```

</TabItem>
</Tabs>

### 定义动态多边形刚体

&emsp;&emsp;动态刚体会受到重力影响，并根据物理世界中的力进行运动。我们可以定义一个多边形刚体，在下例中我们定义了一个六边形。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local polygonDef = BodyDef()
polygonDef.type = "Dynamic" -- 设置为动态刚体
polygonDef.linearAcceleration = gravity -- 应用重力
polygonDef:attachPolygon({
	Vec2(60, 0),
	Vec2(30, -30),
	Vec2(-30, -30),
	Vec2(-60, 0),
	Vec2(-30, 30),
	Vec2(30, 30)
}, 1, 0.4, 0.4) -- 定义一个六边形
```

</TabItem>
</Tabs>

### 定义动态圆形刚体

&emsp;&emsp;圆形刚体类似于多边形，但其形状为圆形，且同样会受到重力影响。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local diskDef = BodyDef()
diskDef.type = "Dynamic" -- 设置为动态刚体
diskDef.linearAcceleration = gravity -- 应用重力
diskDef:attachDisk(60, 1, 0.4, 0.4) -- 附加一个半径为60的圆形
```

</TabItem>
</Tabs>

## 3. 设置分组和碰撞关系

&emsp;&emsp;我们可以通过分组的方式来决定不同物体之间的碰撞关系。在此示例中，我们创建了三个分组，并通过 `setShouldContact` 方法来设置分组之间的碰撞规则。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local groupZero <const> = 0
local groupOne <const> = 1
local groupTwo <const> = 2

world:setShouldContact(groupZero, groupOne, false) -- 组0与组1不碰撞
world:setShouldContact(groupZero, groupTwo, true) -- 组0与组2碰撞
world:setShouldContact(groupOne, groupTwo, true) -- 组1与组2碰撞
world.showDebug = true -- 显示调试信息
```

</TabItem>
</Tabs>

:::tip 物理分组的最佳实践
&emsp;&emsp;在实际游戏开发中，合理设置物理分组可以大大提高性能和降低不必要的计算。建议为游戏中的静态元素、动态物体以及玩家角色等设置不同的分组，并根据需求调整碰撞关系。
:::

## 4. 创建并添加刚体到物理世界

&emsp;&emsp;最后，我们将定义的物理刚体对象进行实例化，并添加到物理世界中。每个刚体可以分配到不同的分组中，并在物理世界中设置初始位置。

<Tabs groupId="language-select">
<TabItem value="lua" label="Lua">

```lua
local Body <const> = require("Body")

-- 创建并添加静态地形刚体
local terrain = Body(terrainDef, world, Vec2.zero)
terrain.group = groupTwo -- 设置刚体分组为组2
world:addChild(terrain)

-- 创建并添加动态多边形刚体
local polygon = Body(polygonDef, world, Vec2(0, 500), 15)
polygon.group = groupOne -- 设置刚体分组为组1
world:addChild(polygon)

-- 创建并添加动态圆形刚体
local disk = Body(diskDef, world, Vec2(50, 800))
disk.group = groupZero -- 设置刚体分组为组0
disk.angularRate = 90 -- 设置旋转速度
world:addChild(disk)
```

</TabItem>
</Tabs>

## 5. 总结

通过本教程，您学会了如何在 Dora SSR 游戏引擎中创建物理刚体，并通过分组的方式控制物体之间的碰撞关系。通过灵活设置刚体的属性、形状和分组，您可以在物理世界中实现复杂的物理效果，并为您的游戏增添更多趣味性。

希望本教程能够帮助您更好地理解 Dora SSR 的物理系统，祝您开发愉快！
